// Time Tracker by Eric Nadeau (nado18@gmail.com)
// Copyright (C) 2007 by Eric Nadeau
// Distributed under the terms of the GNU General Public License (see GPL.txt)

package view;

import java.awt.*;
import java.awt.event.*;

import javax.swing.*;

import model.*;

/**
 * I allow easy editing of a Project object. Simply call my 
 * edit(Frame owner, Project project) method and if the user
 * clicks 'ok' after making changes, the Project object will be
 * updated.
 * 
 * @author Eric Nadeau (nado18@gmail.com), on Apr 21, 2004
 */
public class ProjectEditor extends JDialog {
	private JLabel lName, lInitial, lRate, lElapsed;
	private RegexTextField tfName, tfInitial, tfRate, tfElapsed;
	private JButton bOk, bCancel;

	private GridBagLayout gbl;
	private GridBagConstraints gbc;

	private JPanel panel;

	private boolean choseOk;

	private Project p;

	private ProjectEditor(Frame owner, Project aProject) {
		super(owner, "Project Properties", true);

		p = aProject;

		create();
		place();
		listen();

		choseOk = false;

		double rate = p.getRate();
		String sRate = rate + ((Math.round(rate * 100) % 10 == 0) ? "0" : "");

		double init = p.getInitial();
		String sInit = init + ((Math.round(init * 100) % 10 == 0) ? "0" : "");

		tfRate.setText(sRate);
		tfInitial.setText(sInit);
		tfName.setText(p.getName());
		tfElapsed.setText(TimeConverter.longToString(p.getElapsed()));

		verifyInput();

		pack();

		Dimension ss = Toolkit.getDefaultToolkit().getScreenSize();
		setLocation((ss.width - getWidth()) / 2, (ss.height - getHeight()) / 2);
	}

	private void create() {
		gbl = new GridBagLayout();
		gbc = new GridBagConstraints();

		lName = new JLabel("Project Name", JLabel.LEFT);
		lElapsed = new JLabel("Elapsed Time", JLabel.LEFT);
		lInitial = new JLabel("Initial Payment", JLabel.LEFT);
		lRate = new JLabel("Hourly Rate", JLabel.LEFT);

		tfName = new RegexTextField(".{1,}", "Project Name");
		tfElapsed = new RegexTextField("[0-9]+(:[0-9]{2}){0,2}", "0:0:0", "1024:37:28".length());
		tfInitial = new RegexTextField("[0-9]+(\\.[0-9]{1,2})?", "0.0");
		tfRate = new RegexTextField("[0-9]+(\\.[0-9]{1,2})?", "20.0");

		bOk = new JButton("Ok");
		bCancel = new JButton("Cancel");

		panel = new JPanel();
	}

	private void add(Component child, int x, int y, int width, double weightx, boolean pad) {
		int padLeft = pad ? 10 : 5;
		int padRest = pad ? 10 : 0;

		gbc.gridx = x;
		gbc.gridy = y;
		gbc.gridwidth = width;
		gbc.gridheight = 1;
		gbc.weightx = weightx;
		gbc.weighty = 1.0;
		gbc.insets = new Insets(padRest, padLeft, padRest, padRest);
		gbc.fill = GridBagConstraints.HORIZONTAL;

		panel.add(child, gbc);
	}

	private void addFieldVerifier(RegexTextField field) {
		field.addFormElementListener( new FormElementListener() {
			public void inputChanged() {
				verifyInput();
			}
		});
	}

	private void place() {
		setContentPane(panel);
		panel.setLayout(gbl);

		add(lName, 0, 0, 2, 0, false);
		add(tfName, 0, 1, 2, 1, true);
		add(lElapsed, 0, 2, 2, 0, false);
		add(tfElapsed, 0, 3, 2, 1, true);
		add(lInitial, 0, 4, 1, 0, false);
		add(lRate, 1, 4, 1, 0, false);
		add(tfInitial, 0, 5, 1, 1, true);
		add(tfRate, 1, 5, 1, 1, true);
		add(bOk, 0, 6, 1, 1, true);
		add(bCancel, 1, 6, 1, 1, true);
	}

	private void listen() {
		addFieldVerifier(tfName);
		addFieldVerifier(tfElapsed);
		addFieldVerifier(tfInitial);
		addFieldVerifier(tfRate);

		bOk.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				ok();
			}
		});

		bCancel.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				cancel();
			}
		});
	}

	private void verifyInput() {
		bOk.setEnabled(
			tfName.isInputValid() 
				&& tfElapsed.isInputValid() 
				&& tfInitial.isInputValid() 
				&& tfRate.isInputValid()
		);
	}

	private void ok() {
		p.setElapsed(TimeConverter.stringToLong(tfElapsed.getText()));
		p.setInitial(Double.parseDouble(tfInitial.getText()));
		p.setRate(Double.parseDouble(tfRate.getText()));
		p.setName(tfName.getText());

		choseOk = true;
		dispose();
	}

	private void cancel() {
		choseOk = false;
		dispose();
	}

	private boolean choseOk() {
		return choseOk;
	}

	/**
	 * Edits a given Project and returns <code>true</code> if the user clicked ok.
	 * If the user clicks ok, the Project object is updated directly, otherwise
	 * it's not changed.
	 * @param owner The Frame to give to the dialog as owner
	 * @param aProject The Project to edit
	 * @return <code>true</code> if the user clicks 'ok', <code>false</code> otherwise.
	 */
	public static boolean edit(Frame owner, Project aProject) {
		ProjectEditor edit = new ProjectEditor(owner, aProject);
		edit.show();
		return edit.choseOk();
	}
}